package com.rabbit.icore;

import lombok.Data;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;
import java.util.Map;


@Data
@Component
//@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE,proxyMode = ScopedProxyMode.TARGET_CLASS)
public class ConfirmCallbackImpl implements RabbitTemplate.ConfirmCallback {
    @Autowired
    private RabbitTemplatePlus rabbitTemplatePlus;//手动输入

    //核心方法，confirm回调函数，不管成功还是失败都会执行
    @Override
    public void confirm(CorrelationData correlationData, boolean b, String s) {
        String appId = null;
        try {
            CorrelationDataPlus correlationDataPlus = null;
            if (correlationData instanceof CorrelationDataPlus) {
                correlationDataPlus = (CorrelationDataPlus) correlationData;
            }
            String routingKey = correlationDataPlus.getRoutingKey();//路由键、队列名都是业务名+appId
            appId = routingKey;
            if (b) {
                // 发送成功,仅代表publisher--->exchange这个成功，即使exchange-->queue失败也是成功。
                if (AppContext.getResult(appId) == null) {
                    AppContext.setResult(appId, "code", "2000");
                }
                //回调逻辑已经执行完成，反馈信息result修改好了，减到0，释放主线程，让主线程继续执行返回result
                AppContext.countDown(AppContext.confirmCall + appId);
            } else {
                //发送失败
                //1.获取消息发送的相关信息,（如果转换失败，需要考虑一下处理空指针异常）
                List<String> exchanges = correlationDataPlus.getExchanges();//交换机
                Map body = correlationDataPlus.getBody();//消息体
                int retryCount = correlationDataPlus.getRetryCount();//执行次数

                //执行重发逻辑
                if (retryCount < exchanges.size() * 2) {
                    System.out.println("publisher---->exchange -- 第" + retryCount + "次失败原因: " + s);
                    retryCount++;
                    correlationDataPlus.setRetryCount(retryCount);
                    rabbitTemplatePlus.sendPlus(body, correlationDataPlus);
                } else {
                    AppContext.setResult(appId, "code", "4101");
                    System.out.println("重新路由多次失败,将消息数据记录在数据库或日志并记录失败原因。。。");
                    AppContext.countDown(AppContext.confirmCall + appId);//回调逻辑已经执行完成，反馈信息result修改好了，减到0，释放主线程，让主线程继续执行返回result
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("路由异常--日志记录异常失败原因: " + Arrays.toString(e.getStackTrace()));
            System.out.println("路由异常，将消息数据记录在数据库或日志。。。");
            AppContext.setResult(appId, "code", "4102");
            AppContext.countDown(AppContext.confirmCall + appId);//回调逻辑已经执行完成，反馈信息result修改好了，减到0，释放主线程，让主线程继续执行返回result
        }

    }

}
